using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.Specialized;
using System.Diagnostics.Contracts;
using Konst3d.Efficiency.Suite;
using Konst3d.Efficiency;

// views:
// 1) short - just titles with efficiency score
// 2) medium - title, score, and brief (1 month) history
// 3) detailed - title, score, history with ability to set ranges, ability to expand to show additional info - description, controls, created, etc...

namespace Efficiency.Controls
{
	public enum MonitorListDisplayMode
	{
		Short,
		Brief,
		Detailed
	}

	public enum MonitorListItemType
	{
		Monitor,
		Counter,
		Commandment
	}

	/// <summary>
	/// Interaction logic for MonitorList.xaml
	/// </summary>
	public partial class MonitorList : UserControl
	{
		#region Constants

		private static readonly string[,] STYLES = new[,] {
			{ "ShortMonitorDisplay", "ShortCounterDisplay", "ShortCommandmentDisplay" },
			{ "BriefMonitorDisplay", "BriefCounterDisplay", "BriefCommandmentDisplay" },
			{ "DetailedMonitorDisplay", "DetailedCounterDisplay", "DetailedCommandmentDisplay" }
		};

		#endregion // Constants

		#region Types

		public class MonitorListItem
		{
			#region Properties

			public IMonitor Monitor
			{
				get
				{
					return _monitor;
				}
			}

			public double TotalCount
			{
				get
				{
					return _monitor.GetSummaryValue();
				}
			}

			#endregion // Properties

			#region Constructor

			public MonitorListItem(IMonitor monitor)
			{
				Contract.Requires(monitor != null);
				_monitor = monitor;
			}

			#endregion // Constructor

			#region IMonitorListItem Members

			public string Title
			{
				get
				{
					return _monitor.Title;
				}
			}

			public string Description
			{
				get
				{
					return _monitor.Description;
				}
			}

			public double Efficiency
			{
				get
				{
					return _monitor.GetAverageValue();
				}
			}

			public bool Active
			{
				get
				{
					return _monitor.Active;
				}
			}

			public DateTime Created
			{
				get
				{
					return _monitor.Created;
				}
			}

			#endregion

			#region Fields

			private IMonitor _monitor;

			#endregion // Fields
		}

		#endregion // Types

		#region Dependency Properties

		public static DependencyProperty DisplayModeProperty = DependencyProperty.Register("DisplayMode", typeof(MonitorListDisplayMode), typeof(MonitorList),
			new FrameworkPropertyMetadata(MonitorListDisplayMode.Short, OnDisplayModeChanged));

		public static DependencyProperty ItemTypeProperty = DependencyProperty.Register("ItemType", typeof(MonitorListItemType), typeof(MonitorList),
			new FrameworkPropertyMetadata(MonitorListItemType.Monitor, OnItemTypeChanged));

		public static DependencyProperty MonitorsProperty = DependencyProperty.Register("Monitors", typeof(IEnumerable<IMonitor>), typeof(MonitorList),
			new FrameworkPropertyMetadata(null, OnMonitorsChanged));

		public static DependencyProperty SelectedProperty = DependencyProperty.Register("Selected", typeof(IMonitor), typeof(MonitorList),
			new FrameworkPropertyMetadata(null, OnSelectedChanged));

		#endregion // Dependency Properties

		#region Routed Events

		public static readonly RoutedEvent ItemDoubleClickEvent = EventManager.RegisterRoutedEvent("ItemDoubleClick", RoutingStrategy.Bubble,
			typeof(RoutedPropertyChangedEventHandler<IMonitor>), typeof(MonitorList));

		#endregion // Routed Events

		#region Properties

		public MonitorListDisplayMode DisplayMode
		{
			get
			{
				return (MonitorListDisplayMode)GetValue(DisplayModeProperty);
			}
			set
			{
				SetValue(DisplayModeProperty, value);
			}
		}

		public MonitorListItemType ItemType
		{
			get
			{
				return (MonitorListItemType)GetValue(ItemTypeProperty);
			}
			set
			{
				SetValue(ItemTypeProperty, value);
			}
		}

		public IEnumerable<IMonitor> Monitors
		{
			get
			{
				return (IEnumerable<IMonitor>)GetValue(MonitorsProperty);
			}
			set
			{
				SetValue(MonitorsProperty, value);
			}
		}

		public IMonitor Selected
		{
			get
			{
				return (IMonitor)GetValue(SelectedProperty);
			}
			set
			{
				SetValue(SelectedProperty, value);
			}
		}

		public IEnumerable<MonitorListItem> Items
		{
			get
			{
				return _items;
			}
		}

		#endregion // Properties

		#region Events

		public event RoutedPropertyChangedEventHandler<IMonitor> ItemDoubleClick
		{
			add
			{
				AddHandler(ItemDoubleClickEvent, value);
			}
			remove
			{
				RemoveHandler(ItemDoubleClickEvent, value);
			}
		}

		#endregion // Events

		#region Constructor

		public MonitorList()
		{
			InitializeComponent();
		}

		#endregion // Constructor

		#region Dependency Properties' Handlers

		private static void OnDisplayModeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
		{
			MonitorList control = sender as MonitorList;
			Contract.Assert(control != null);

			control.UpdateTemplate();
		}

		private static void OnItemTypeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
		{
			MonitorList control = sender as MonitorList;
			Contract.Assert(control != null);

			control.UpdateTemplate();
		}

		private static void OnMonitorsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
		{
			MonitorList control = sender as MonitorList;
			Contract.Assert(control != null);

			// TOFIX: remove somehow dewlegate on old collection

			var notifyCollection = control.Monitors as INotifyCollectionChanged;

			if (notifyCollection != null)
			{
				notifyCollection.CollectionChanged += control.OnMonitorCollectionChanged;
			}

			control.UpdateItems();
		}

		private static void OnItemsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
		{
			MonitorList control = sender as MonitorList;
			Contract.Assert(control != null);
		}

		private void OnMonitorCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			UpdateItems();
		}

		private static void OnSelectedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
		{
			MonitorList control = sender as MonitorList;
			Contract.Assert(control != null);

			// TOFIX: any additional logic for TwoWay binding support?
		}

		#endregion // Dependency Properties' Handlers

		#region UI Event Handlers

		private void OnListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			MonitorListItem item = uiMainListBox.SelectedItem as MonitorListItem;

			Selected = item != null ? item.Monitor : null;
		}

		private void OnListBoxMouseDoubleClick(object sender, MouseButtonEventArgs e)
		{
			var listBox = sender as ListBox;

			Contract.Assert(listBox != null);

			var monitorEntry = listBox.SelectedItem as MonitorListItem;

			Contract.Assert(monitorEntry != null);

			RoutedPropertyChangedEventArgs<IMonitor> args = new RoutedPropertyChangedEventArgs<IMonitor>(null, monitorEntry.Monitor);
			args.RoutedEvent = MonitorList.ItemDoubleClickEvent;

			RaiseEvent(args);
		}

		#endregion // UI Event Handlers

		#region Private Methods

		private void UpdateItems()
		{
			_items.BeginUpdate();
			_items.Clear();

			if (Monitors != null)
			{
				foreach (var monitor in Monitors)
				{
					_items.Add(new MonitorListItem(monitor));
				}
			}

			_items.EndUpdate();
		}

		private void UpdateTemplate()
		{
			/*
			switch (DisplayMode)
			{
				case MonitorListDisplayMode.Short:
					uiMainListBox.Style = FindResource("ShortDisplay") as Style;
					break;

				case MonitorListDisplayMode.Brief:
					uiMainListBox.Style = FindResource("BriefDisplay") as Style;
					break;

				case MonitorListDisplayMode.Detailed:
					uiMainListBox.Style = FindResource("DetailedDisplay") as Style;
					break;
			}
			*/
			uiMainListBox.Style = FindResource(STYLES[(int)DisplayMode, (int)ItemType]) as Style;
		}

		#endregion // Private Methods

		#region Fields

		private ObservableList2<MonitorListItem> _items = new ObservableList2<MonitorListItem>();

		#endregion // Fields
	}

	public class BriefItemStartDateCalculator : IValueConverter
	{
		#region IValueConverter Members

		public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
		{
			var monitor = value as IMonitor;
			var start = DateTime.Now.Date;

			if (monitor != null)
			{
				if (monitor.Created.Date <= DateTime.Now.Date.AddDays(-31))
				{
					start = DateTime.Now.Date.AddDays(-31);
				}
				else
				{
					start = monitor.Created;
				}
			}

			return start;
		}

		public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
		{
			throw new NotImplementedException();
		}

		#endregion
	}
}
